#ifndef __MPU6050_H
#define __MPU6050_H

#include "ti_msp_dl_config.h"
#include <stdint.h>
#include <stdbool.h>

/****************************************************************************************************************/
/*                                        MPU6050 Register Definitions                                         */
/****************************************************************************************************************/

// MPU6050 Register Map
#define MPU_SELF_TESTX_REG      0x0D    // Self Test X
#define MPU_SELF_TESTY_REG      0x0E    // Self Test Y
#define MPU_SELF_TESTZ_REG      0x0F    // Self Test Z
#define MPU_SELF_TESTA_REG      0x10    // Self Test A
#define MPU_SAMPLE_RATE_REG     0x19    // Sample Rate Divider
#define MPU_CFG_REG             0x1A    // Configuration
#define MPU_GYRO_CFG_REG        0x1B    // Gyroscope Configuration
#define MPU_ACCEL_CFG_REG       0x1C    // Accelerometer Configuration
#define MPU_MOTION_DET_REG      0x1F    // Motion Detection Threshold
#define MPU_FIFO_EN_REG         0x23    // FIFO Enable
#define MPU_I2CMST_CTRL_REG     0x24    // I2C Master Control
#define MPU_I2CSLV0_ADDR_REG    0x25    // I2C Slave 0 Address
#define MPU_I2CSLV0_REG         0x26    // I2C Slave 0 Register
#define MPU_I2CSLV0_CTRL_REG    0x27    // I2C Slave 0 Control
#define MPU_I2CSLV1_ADDR_REG    0x28    // I2C Slave 1 Address
#define MPU_I2CSLV1_REG         0x29    // I2C Slave 1 Register
#define MPU_I2CSLV1_CTRL_REG    0x2A    // I2C Slave 1 Control
#define MPU_I2CSLV2_ADDR_REG    0x2B    // I2C Slave 2 Address
#define MPU_I2CSLV2_REG         0x2C    // I2C Slave 2 Register
#define MPU_I2CSLV2_CTRL_REG    0x2D    // I2C Slave 2 Control
#define MPU_I2CSLV3_ADDR_REG    0x2E    // I2C Slave 3 Address
#define MPU_I2CSLV3_REG         0x2F    // I2C Slave 3 Register
#define MPU_I2CSLV3_CTRL_REG    0x30    // I2C Slave 3 Control
#define MPU_I2CSLV4_ADDR_REG    0x31    // I2C Slave 4 Address
#define MPU_I2CSLV4_REG         0x32    // I2C Slave 4 Register
#define MPU_I2CSLV4_DO_REG      0x33    // I2C Slave 4 Data Out
#define MPU_I2CSLV4_CTRL_REG    0x34    // I2C Slave 4 Control
#define MPU_I2CSLV4_DI_REG      0x35    // I2C Slave 4 Data In

#define MPU_I2CMST_STA_REG      0x36    // I2C Master Status
#define MPU_INTBP_CFG_REG       0x37    // INT Pin / Bypass Enable Configuration
#define MPU_INT_EN_REG          0x38    // Interrupt Enable
#define MPU_INT_STA_REG         0x3A    // Interrupt Status

#define MPU_ACCEL_XOUTH_REG     0x3B    // Accelerometer X-axis High Byte
#define MPU_ACCEL_XOUTL_REG     0x3C    // Accelerometer X-axis Low Byte
#define MPU_ACCEL_YOUTH_REG     0x3D    // Accelerometer Y-axis High Byte
#define MPU_ACCEL_YOUTL_REG     0x3E    // Accelerometer Y-axis Low Byte
#define MPU_ACCEL_ZOUTH_REG     0x3F    // Accelerometer Z-axis High Byte
#define MPU_ACCEL_ZOUTL_REG     0x40    // Accelerometer Z-axis Low Byte

#define MPU_TEMP_OUTH_REG       0x41    // Temperature High Byte
#define MPU_TEMP_OUTL_REG       0x42    // Temperature Low Byte

#define MPU_GYRO_XOUTH_REG      0x43    // Gyroscope X-axis High Byte
#define MPU_GYRO_XOUTL_REG      0x44    // Gyroscope X-axis Low Byte
#define MPU_GYRO_YOUTH_REG      0x45    // Gyroscope Y-axis High Byte
#define MPU_GYRO_YOUTL_REG      0x46    // Gyroscope Y-axis Low Byte
#define MPU_GYRO_ZOUTH_REG      0x47    // Gyroscope Z-axis High Byte
#define MPU_GYRO_ZOUTL_REG      0x48    // Gyroscope Z-axis Low Byte

#define MPU_I2CSLV0_DO_REG      0x63    // I2C Slave 0 Data Out
#define MPU_I2CSLV1_DO_REG      0x64    // I2C Slave 1 Data Out
#define MPU_I2CSLV2_DO_REG      0x65    // I2C Slave 2 Data Out
#define MPU_I2CSLV3_DO_REG      0x66    // I2C Slave 3 Data Out

#define MPU_I2CMST_DELAY_REG    0x67    // I2C Master Delay Control
#define MPU_SIGPATH_RST_REG     0x68    // Signal Path Reset
#define MPU_MDETECT_CTRL_REG    0x69    // Motion Detection Control
#define MPU_USER_CTRL_REG       0x6A    // User Control
#define MPU_PWR_MGMT1_REG       0x6B    // Power Management 1
#define MPU_PWR_MGMT2_REG       0x6C    // Power Management 2
#define MPU_FIFO_CNTH_REG       0x72    // FIFO Count High Byte
#define MPU_FIFO_CNTL_REG       0x73    // FIFO Count Low Byte
#define MPU_FIFO_RW_REG         0x74    // FIFO R/W
#define MPU_DEVICE_ID_REG       0x75    // Who Am I

// MPU6050 I2C Address (AD0 pin to GND)
#define MPU6050_ADDR            0x68

// MPU6050/MPU6500 Device IDs
#define MPU6050_DEVICE_ID       0x68
#define MPU6500_DEVICE_ID       0x70
#define MPU9250_DEVICE_ID       0x71

// Gyroscope Full Scale Range
#define MPU_GYRO_FSR_250DPS     0    // ±250 dps
#define MPU_GYRO_FSR_500DPS     1    // ±500 dps
#define MPU_GYRO_FSR_1000DPS    2    // ±1000 dps
#define MPU_GYRO_FSR_2000DPS    3    // ±2000 dps

// Accelerometer Full Scale Range
#define MPU_ACCEL_FSR_2G        0    // ±2g
#define MPU_ACCEL_FSR_4G        1    // ±4g
#define MPU_ACCEL_FSR_8G        2    // ±8g
#define MPU_ACCEL_FSR_16G       3    // ±16g

/****************************************************************************************************************/
/*                                        Data Structures                                                      */
/****************************************************************************************************************/

// MPU6050 Data Structure
typedef struct {
    int16_t accel_x;    // Accelerometer X-axis raw data
    int16_t accel_y;    // Accelerometer Y-axis raw data
    int16_t accel_z;    // Accelerometer Z-axis raw data
    int16_t temp;       // Temperature raw data
    int16_t gyro_x;     // Gyroscope X-axis raw data
    int16_t gyro_y;     // Gyroscope Y-axis raw data
    int16_t gyro_z;     // Gyroscope Z-axis raw data
} MPU6050_Data_t;

// MPU6050 Configuration Structure
typedef struct {
    uint8_t gyro_fsr;     // Gyroscope full scale range
    uint8_t accel_fsr;    // Accelerometer full scale range
    uint16_t sample_rate; // Sample rate (Hz)
    uint16_t lpf_freq;    // Low pass filter frequency (Hz)
} MPU6050_Config_t;

/****************************************************************************************************************/
/*                                        Function Declarations                                                */
/****************************************************************************************************************/

// Initialization and Configuration Functions
uint8_t MPU6050_Init(void);
uint8_t MPU6050_Test_Connection(void);
uint8_t MPU6050_Set_Gyro_FSR(uint8_t fsr);
uint8_t MPU6050_Set_Accel_FSR(uint8_t fsr);
uint8_t MPU6050_Set_LPF(uint16_t lpf);
uint8_t MPU6050_Set_Rate(uint16_t rate);
uint8_t MPU6050_Set_FIFO(uint8_t sens);

// Data Reading Functions
uint8_t MPU6050_Read_All_Data(MPU6050_Data_t *data);
uint8_t MPU6050_Get_Accelerometer(int16_t *ax, int16_t *ay, int16_t *az);
uint8_t MPU6050_Get_Gyroscope(int16_t *gx, int16_t *gy, int16_t *gz);
int16_t MPU6050_Get_Temperature(void);

// Low-level I2C Functions
uint8_t MPU6050_Write_Byte(uint8_t reg, uint8_t data);
uint8_t MPU6050_Read_Byte(uint8_t reg);
uint8_t MPU6050_Write_Len(uint8_t reg, uint8_t len, uint8_t *buf);
uint8_t MPU6050_Read_Len(uint8_t reg, uint8_t len, uint8_t *buf);

// Utility Functions
void MPU6050_Reset(void);
uint8_t MPU6050_Sleep(bool enable);

// Debug Functions
uint8_t MPU6050_Debug_Init(void);
void MPU6050_Debug_I2C_Scan(void);

#endif /* __MPU6050_H */
